/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SPATIAL_RDB_MANAGER_H
#define SPATIAL_RDB_MANAGER_H

#include <memory>
#include <random>
#include <string>
#include <vector>

#include "rdb_store.h"
#include "rdb_helper.h"
#include "rdb_open_callback.h"
#include "rdb_store_config.h"
#include "values_bucket.h"
#include "result_set.h"
#include "timer.h"
#include "common_timer_errors.h"
#include "msdp_algorithm_common.h"
#include "spatial_timer.h"

namespace OHOS {
namespace Msdp {
class SpatialRdbManager {
public:
    using SpatialEventCallback = std::function<bool(const SpatialEvent &event)>;
    SpatialRdbManager();
    ~SpatialRdbManager()
    {
        timerUtils_->Stop();
    }
    enum {
        CMD_DIRECTION = 0,
        CMD_DISTANCE,
        CMD_ANGLE,
        CMD_INNEROUTER,
        CMD_EXIST,
        CMD_COMMON,
    };
    bool Init(int mode);
    /* spatial event */
    void RegisterEventCallback(int mode, SpatialEventCallback& callback);
    void UpdateSpatialEventData(int mode);
private:
    /* Timer */
    bool InitTimer();
    void InitTimerInfo();
    bool StartTimer(int milliseconds, bool once);
    void StopTimer();
    /* Rdb database operation */
    int32_t CreateRdbStore();
    void InsertSpatialRelation(std::shared_ptr<NativeRdb::RdbStore> &store);
    void UpdateSpatialRelation();
    void CheckSpatialRelation(std::shared_ptr<NativeRdb::RdbStore> &store);
    void GetSpatialData(std::unique_ptr<NativeRdb::ResultSet> &resultSet);
    void CheckSpatialDirectionValue(std::shared_ptr<NativeRdb::RdbStore> &store);
    void CheckSpatialDistanceValue(std::shared_ptr<NativeRdb::RdbStore> &store);
    void CheckSpatialAngleValue(std::shared_ptr<NativeRdb::RdbStore> &store);
    void CheckSpatialInnerOuterValue(std::shared_ptr<NativeRdb::RdbStore> &store);
    void CheckSpatialExistValue(std::shared_ptr<NativeRdb::RdbStore> &store);
    void UpdateDirectionData();
    void UpdateDistanceData();
    void UpdateAngleData();
    void UpdateInnerOuterData();
    void UpdateExistData();
    void CheckDeviceData(int mode, std::shared_ptr<NativeRdb::RdbStore> &store);
    void GetDeviceData(int32_t mode, std::unique_ptr<NativeRdb::ResultSet> &resultSet);
    void UpdateDeviceData(int mode, int deviceType, const std::string deviceId, const std::string deviceName);
    std::shared_ptr<NativeRdb::RdbStore> store_;
    std::unique_ptr<NativeRdb::ValuesBucket> directionValues_;
    std::unique_ptr<NativeRdb::ValuesBucket> distanceValues_;
    std::unique_ptr<NativeRdb::ValuesBucket> angleValues_;
    std::unique_ptr<NativeRdb::ValuesBucket> innerOuterValues_;
    std::unique_ptr<NativeRdb::ValuesBucket> existValues_;
    SpatialEvent directionEvent_;
    SpatialEvent distanceEvent_;
    SpatialEvent angleEvent_;
    SpatialEvent innerOuterEvent_;
    SpatialEvent existEvent_;
    SpatialEvent commonEvent_;
    SpatialEventCallback directionCb_;
    SpatialEventCallback distanceCb_;
    SpatialEventCallback angleCb_;
    SpatialEventCallback innerOuterCb_;
    SpatialEventCallback existCb_;
    SpatialEventCallback commonCb_;
    NativeRdb::ValuesBucket commonValues_;
    Utils::Timer timer_;
    std::shared_ptr<SpatialTimer> timerUtils_;
};

class InsertOpenCallback : public NativeRdb::RdbOpenCallback {
public:
    int OnCreate(NativeRdb::RdbStore &rdbStore) override;
    int OnUpgrade(NativeRdb::RdbStore &rdbStore, int oldVersion, int newVersion) override;
};
} // Msdp
} // OHOS
#endif // SPATIAL_RDB_MANAGER_H